          SUBROUTINE (VAL,ATTB)
** Version# 0.0002[2] - 05/04/2017 - 11:47am - TSMITH - eclipse
*** V0.0002 Change - Custom Coding . - 05/04/2017 - TSMITH - eclipse

*** Subroutine: DICT.GET.LEDGER.VALUE
*-------------------------------------------------------------------------*
*** This subroutine will return a data value for a given LEDGER Record.
*** It is intended to be called primarily from dictionary I-descriptors
*** or I-descriptor subroutines, and from Report Writer / Mass Load.
*** It will attempt to find the correct generation based on the @ID of the
*** record (PSUB/OSUB IDs, OID+INVN, OID+GID, etc.)  If it cannot determine
*** the correct generation based on the @ID, it will return the data from
*** the specified attribute for all generations (usually VM-delimited by
*** generation).
*** NOTE: Some of the special cases (line item data, invoice print
*** date) require a generation and will return a blank value if the
*** correct generation cannot be found based on the @ID.
*-------------------------------------------------------------------------*
*** Parameters:
***  @ID  - (implied parameter) - the ID of the ledger record      (IN)
***  VAL  - The value returned from the LEDGER record              (OUT)
***  ATTB - The attribute number of the data to return             (IN)
***         This can also be an alphanumeric code which will return
***         a special type of data (line item info, invoice print dt, etc)
*-------------------------------------------------------------------------*
*** Common Vars:
***  This routine has the possibility of overwriting the LED, LD, PRD,
***  PRDD.BR, PLNE arrays
*-------------------------------------------------------------------------*

          VAL = ""
          CERR = ''
          * Ordered by field, this may need to be looked up
          * in the contacts file.
          IF ATTB = 68 THEN
             UT.OPEN.FILE "CONTACT",CFILE,CERR,YES
          END

          * If a dictionary is based on two other dictionaries,
          * we need to keep @ID the same for calculation of both dicts.
          * e.g. Ledger~ER_GP$_COGS = ER_UNIT_PRC - ER_COGS
          LOCAL.ID = @ID

          GOSUB GET.GEN           ;* try and figure out the generation

          GOSUB GET.DATA          ;* get the data from the ledger record

          RETURN
*-------------------------------------------------------------------------*
GET.GEN:  *** try and get the generation of the order to use

          GEN = 0
          * get the # of '.'-delimited fields in the ID
          PASS.LDID = 0
          IF INDEX(@ID,'^',1) THEN
             PASS.LDID = FIELD(@ID,'^',2)
             IF NOT(NUM(PASS.LDID)) THEN PASS.LDID = 0
             PASS.LDID += 0
             LOCAL.ID = FIELD(@ID,'^',1)
          END
          GN  = DCOUNT(LOCAL.ID,'.')

          BEGIN CASE
          CASE INDEX(LOCAL.ID,'~',1)
             OID = FIELD(LOCAL.ID,'~',4)
             IDX = FIELD(LOCAL.ID,'~',5)
             GEN.ATTR = 8
             * OSUB file has GID in IDX value of ID
             IF @FILENAME = 'OSUB' THEN GEN.ATTR = 12
             READV GEN.IDX FROM LEDFILE,OID,GEN.ATTR ELSE GEN.IDX = ''
          CASE GN=4
             OID = FIELD(LOCAL.ID,'.',3)
             IDX = FIELD(LOCAL.ID,'.',4)+0
             READV GEN.IDX FROM LEDFILE,OID,12 ELSE  GEN.IDX = ''
          CASE GN = 2
             OID = FIELD(LOCAL.ID,'.',1)
             IDX = FIELD(LOCAL.ID,'.',2)+0
             READV GEN.IDX FROM LEDFILE,OID,8 ELSE GEN.IDX = ''
          CASE OTHERWISE
             OID = FIELD(LOCAL.ID,'.',1)
             IDX = FIELD(LOCAL.ID,'.',3)+0
             READV GEN.IDX FROM LEDFILE,OID,12 ELSE GEN.IDX = ''
          END CASE

          *** If we can't find the generation, set it to zero so
          *** we will get all the values in the attribute
          IF IDX AND GEN.IDX<1> THEN
             LOCATE IDX IN GEN.IDX<1> SETTING GEN ELSE GEN = 0
          END
          IF GEN = 0 THEN
             * DICT.COMMON<9> stores the multi-value position
             GEN = DICT.COMMON<9>
          END

          IF GEN = '' THEN
             GEN = 0
          END

          RETURN
*-------------------------------------------------------------------------*
GET.DATA: *** get the data value from the ledger record

          OE.GET.QSIGN QSIGN,OID
          BEGIN CASE
          CASE NUM(ATTB)
             * standard case - return data for the specified attribute
             READV VALS FROM LEDFILE,OID,ATTB ELSE VALS = ''

             IF GEN = 0 THEN
                GEN.CT.START = 1
                GEN.CT.END = DCOUNT(VALS,VM)
             END ELSE
                GEN.CT.START = GEN
                GEN.CT.END = GEN
             END
             FINAL.VAL = ""
             * If the Gen is 0 we need to go ahead and loop through each
             * GEN. Otherwise we will set Start and End to GEN so that we
             * only loop through the given GEN.
             FOR GEN.POS = GEN.CT.START TO GEN.CT.END
                VAL = VALS<1,GEN.POS>
                * Special rules for some of the given ATTBs that are gen
                * dependent.
                IF ATTB = 42 THEN
                   FINAL.VAL<1,-1> = OCONV(ICONV(OCONV(VAL * QSIGN,'MR9'),'MR2'),'MR2')
                END ELSE IF ATTB = 64 THEN
                   * LED(64) has SVM delimite tax items
                   FINAL.VAL<1,-1> = SUM(VAL)
                END ELSE IF ATTB>13 AND ATTB<19 THEN
                   FINAL.VAL<1,-1> = VAL * QSIGN
                END ELSE IF ATTB = 68 AND NOT(CERR) THEN
                   TEMP.VAL = VAL
                   IF (TEMP.VAL[1,1] = "#") THEN
                      TEMP.VAL = TRIM(TEMP.VAL[2,99])
                      READ CREC FROM CFILE,TEMP.VAL THEN
                         TEMP.VAL  = TRIM(CREC<3>):", ":TRIM(CREC<1>):" "
                         TEMP.VAL := TRIM(CREC<2>)
                      END ELSE
                         TEMP.VAL  = ""
                      END
                   END
                   FINAL.VAL<1,-1> = TEMP.VAL
                END ELSE
                   * The value just needs to be sent as is.
                   FINAL.VAL<1,-1> = VAL
                END
             NEXT GEN.POS
             * Replace the value with the calculated values.
             VAL = FINAL.VAL
          CASE ATTB[1,3] = "ID."
             * special case - pulling a field from the LOCAL.ID
             POS = FIELD(ATTB,'.',2)
             VAL = FIELD(LOCAL.ID,'.',POS+2)
             RETURN
          CASE ATTB[1,3]= "HF."
             * Special situation for Total Handling and Frieght
             POS = FIELD(ATTB,".",2)
             SPOS = FIELD(ATTB,".",3)

             READV VALS FROM LEDFILE,OID,POS ELSE VALS = ''
             VAL =  OCONV(VALS<1,SPOS>,"MR2")
             RETURN
          CASE ATTB[1,3] = 'LI.'
             * special case for line item data
             GOSUB GET.LI.DATA
          CASE ATTB[1,3]='TV.'
             * special case for PN, Name, or Bid Followup dates
             TYPE=ATTB[4,99]
             BEGIN CASE
                CASE TYPE = 'PN'
                   IF NUM(PN) THEN
                      VAL<1,LDN> = PN
                   END ELSE VAL<1,LDN> = ''
                CASE TYPE = 'NAME'
                   *** we require a valid generation to get line item data
                   IF GEN+0=0 THEN RETURN
                   READV CN FROM LEDFILE,OID,5 ELSE CN=''
                   CN = CN<1,GEN>
                   READV VAL FROM CUSFILE,CN,1 ELSE VAL=''
                CASE TYPE = 'BFLW.DT'
                   VAL=''
                   READ REC FROM LEDLFILE,OID ELSE REC=''
                   DTS=DCOUNT(REC<11>,VM)
                   FOR DTCT = 1 TO DTS
                   IF REC<11,DTCT> GT 0 THEN
                      VAL<1,-1>=REC<11,DTCT>
                      END
                   NEXT DTCT
             END CASE
          CASE ATTB = 'INV.PRT.DATE'
             * special case for the invoice print date
             VAL = ''
             *** we need a valid gen to get this data
             IF GEN+0 = 0 THEN RETURN

             READ LEDL.REC FROM LEDLFILE,OID ELSE LEDL.REC = ''
             LOCATE 'I' IN LEDL.REC<1,GEN> SETTING IPOS ELSE RETURN
             VAL = LEDL.REC<39,GEN,IPOS>

             *** Make it work on orders before rel8.0 (the slow way)
             IF NOT(VAL) THEN
                MATREAD LED FROM LEDFILE,OID ELSE MAT LED = ''
                CMTS = RAISE(OCONV(TRIM(LEDL.REC<10>),'MCU'))
                CT   = 0

                LOOP
                   CT += 1
                   FINDSTR 'PRINTED INVOICE' IN CMTS,CT SETTING AP THEN
                      *** Make sure it's our GID
                      IF CMTS<AP,1> = LED(12)<1,GEN> THEN
                         VAL = CMTS<AP,2>
                         EXIT
                      END
                   END ELSE
                      EXIT
                   END
                REPEAT
             END
          CASE ATTB[1,5] = 'DICT.'
             * Special case to allow passing of another dictionary item.
             DICT = TRIM(ATTB[6,99])
             READ LDATA FROM LEDFILE,OID ELSE LDATA = ''
             GET.DICT.VALUE DICT,'LEDGER',OID,LDATA,VALS
             VAL = VALS<1,GEN>
          END CASE

          RETURN
*-------------------------------------------------------------------------*
GET.LI.DATA:*** Get Line Item data

          *** we require a valid generation to get line item data
          IF GEN+0=0 THEN RETURN

          TYPE    = ATTB[4,99]
          VAL     = ''

          MATREAD LED FROM LEDFILE,OID ELSE MAT LED = ''
          LDIDS   = LED(48)<1,GEN>
          IF PASS.LDID THEN
             LDIDS = PASS.LDID
          END
          LD.CT   = DCOUNT(LDIDS,SVM)

          FOR LDN = 1 TO LD.CT
          LDID = LDIDS<1,1,LDN>
          LD.GET LDID
          PN = LD(1)

          BEGIN CASE
          CASE NUM(FIELD(TYPE,',',1))
             MATBUILD WRK FROM LD
             TEMPV = WRK<TYPE>
             ATTR.NO = FIELD(TYPE,',',1)
             * handle override price, cogs and comm cost
             IF ATTR.NO = 9 OR ATTR.NO = 11 OR ATTR.NO = 28 THEN
                TEMPV = ICONV(OCONV(TEMPV,'MR9'),'MR2')
             END
             VAL<1,LDN> = TEMPV

          CASE TYPE[1,3] = 'JM.'
             UT.OPEN.FILE 'JM.ITEM.DETAIL',JMFILE,ERR.MSG,YES
             IF ERR.MSG THEN
                VAL = ''
                RETURN
             END
             JM.ID = OID:'.':LDID
             JM.ATTR = TYPE[4,99]
             READV JVAL FROM JMFILE, JM.ID, JM.ATTR ELSE JVAL = ''
             * conversion for price and cost
             IF JM.ATTR = 10 OR JM.ATTR = 8 THEN
                JVAL = ICONV(OCONV(JVAL,'MR9'),'MR2')
             END
             VAL<1,LDN> = JVAL

          CASE TYPE = 'PN'
             IF NUM(PN) THEN
                VAL<1,LDN> = PN
             END ELSE VAL<1,LDN> = ''
          CASE TYPE[1,8] = 'LOCATION'
             * return a VM list of locations
             LOCS = RAISE(LD(7)<1,GEN>)
             LOC.CNT = DCOUNT(LOCS,VM)
             RET.VAL = ''
             FOR LOC.IND = 1 TO LOC.CNT
                RET.VAL<1,LOC.IND> = FIELD(LOCS<1,LOC.IND>,'~',2)
             NEXT LOC.IND
             VAL<1,LDN> = RET.VAL
          CASE TYPE[1,8] = 'LOC.SQTY'
             * return a VM list of ship qty for the locations
             LOC5 = RAISE(LD(5)<1,GEN>)
             LOC6 = RAISE(LD(6)<1,GEN>)
             LOC.CNT = DCOUNT(LOC5,VM)
             RET.VAL = ''
             FOR LOC.IND = 1 TO LOC.CNT
                RET.VAL<1,LOC.IND> = (LOC5<1,LOC.IND> + LOC6<1,LOC.IND>) * QSIGN
             NEXT LOC.IND
             VAL<1,LDN> = RET.VAL
          CASE TYPE[1,4] = 'SQTY'
             BEGIN CASE
             CASE NUM(PN)
                SP.QTY = (SUM(LD(5)<1,GEN>) + SUM(LD(6)<1,GEN>))*QSIGN
                IF TYPE = 'SQTY.PER' THEN
                   *** convert the UOM qty.
                   MATREAD PRD FROM PRDFILE,PN ELSE MAT PRD = ''
                   IF PRD(15) # '' THEN
                      UMTBL = PRD(15)
                   END ELSE
                      READV UMTBL FROM PLNEFILE,PRD(9),3 ELSE UMTBL = ''
                   END
                   IQ.TO.ALPHA.GPS UMTBL,PRD(7),LD(23),SP.QTY,,,,,ALPHA
                   SP.QTY = TRIM(ALPHA)
                END
                VAL<1,LDN> = SP.QTY
             CASE OTHERWISE
                VAL<1,LDN> = '*'
             END CASE
          CASE TYPE[1,4] = 'OQTY'
             BEGIN CASE
             CASE NUM(PN)
                ORD.QTY = LD(4)*QSIGN
                IF TYPE = 'OQTY.PER' THEN
                   *** convert the UOM qty.
                   MATREAD PRD FROM PRDFILE,PN ELSE MAT PRD = ''
                   IF PRD(15) # '' THEN
                      UMTBL = PRD(15)
                   END ELSE
                      READV UMTBL FROM PLNEFILE,PRD(9),3 ELSE UMTBL = ''
                   END
                   IQ.TO.ALPHA UMTBL,PRD(7),LD(23),ORD.QTY,,,,,ALPHA
                   ORD.QTY = TRIM(ALPHA)
                END
                VAL<1,LDN> = ORD.QTY
             CASE OTHERWISE
                VAL<1,LDN> = '*'
             END CASE
          CASE TYPE = 'CT'
             BEGIN CASE
             CASE NUM(PN)
                VAL<1,LDN> = 1
             CASE OTHERWISE
                VAL<1,LDN> = 0
             END CASE
          CASE TYPE[1,4] = 'DESC'
             IF NUM(PN) THEN
                READV DESC FROM PRDFILE,PN,1 ELSE DESC = '* Not Found *'
             END ELSE DESC = ''
             IF LD(3)#'' THEN DESC<1,-1> = LD(3)
             SVCHK = TYPE[5,99]
             BEGIN CASE
             CASE SVCHK = "W"
                VAL<1,LDN> = FIELD(DESC,' ',1)
             CASE TRIM(SVCHK) = '' OR NOT(NUM(SVCHK))
                VAL<1,LDN> = LOWER(DESC)
             CASE OTHERWISE
                VAL<1,LDN> = DESC<1,SVCHK>
             END CASE
          CASE TYPE[1,4] = 'ENT#'
             IF NUM(PN) THEN
                FOUND  = NO
                CMT.CT = DCOUNT(LD(3)<1>,VM)
                FOR JT = 1 TO CMT.CT
                IF OCONV(LD(3)<1,JT>,'MCU')[1,6] = 'YOUR #' THEN
                   VAL<1,LDN> = TRIM(FIELD(LD(3)<1,JT>,'#',2))
                   FOUND = YES
                   EXIT
                END
                NEXT JT
                IF NOT(FOUND) THEN
                   OE.CUS.PN.CMT.GET LED(1)<1,GEN>,LED(5)<1,GEN>,,PN,CMT
                   VAL<1,LDN> = CMT<1,1,1>
                END
             END
          CASE TYPE = 'PRCLN'
             IF NUM(PN) THEN
                READV PRCLN FROM PRDFILE,PN,9 ELSE PRCLN = '* Not Found *'
             END ELSE PRCLN = ''
             VAL<1,LDN> = PRCLN
          CASE TYPE = 'PRCEXT'
             SQTY       = (SUM(LD(5)<1,GEN>)+SUM(LD(6)<1,GEN>))*QSIGN
             VAL<1,LDN> = ICONV(OCONV(LD(8)<1,GEN>,'MR9')*SQTY,'MR2')
          CASE TYPE = 'UNIT'
             VAL<1,LDN> = ICONV(OCONV(LD(8)<1,GEN>,'MR9'),'MR2')
          CASE TYPE = 'UNIT_COGS'
             VAL<1,LDN> = ICONV(OCONV(LD(10)<1,GEN>,'MR9'),'MR2')
          CASE TYPE = 'UNIT_COMM_COST'
             VAL<1,LDN> = ICONV(OCONV(LD(27)<1,GEN>,'MR9'),'MR2')
          CASE TYPE = 'CSTEXT'
             SQTY       = (SUM(LD(5)<1,GEN>)+SUM(LD(6)<1,GEN>))*QSIGN
             VAL<1,LDN> = ICONV(OCONV(LD(10)<1,GEN>,'MR9')*SQTY,'MR2')
          CASE TYPE = 'COMEXT'
             SQTY       = (SUM(LD(5)<1,GEN>)+SUM(LD(6)<1,GEN>))*QSIGN
             VAL<1,LDN> = ICONV(OCONV(LD(27)<1,GEN>,'MR9')*SQTY,'MR2')
          CASE TYPE = 'TYPE'
             VAL<1,LDN> = FIELD(LD(7)<1,GEN>,'~',1)
          CASE TYPE = 'TAG' OR TYPE = 'TAGDT'
             LOCA = FIELD(LD(7)<1,GEN>,'~',2)
             TAG  = FIELD(LOCA,'^',2)
             TAG  = FIELD(TAG,".",1)
             LOCATE TAG IN VAL<1> BY "AL" SETTING TLOC ELSE
                VAL = INSERT(VAL,1,TLOC;TAG)
             END
          CASE TYPE[1,6] = 'ONHAND'
             STK.BR = LED(2)<1,GEN,2>
             IF NUM(PN) THEN
                PRDD.BR.GET.REC STK.BR,PN,REC
                GET.ONHAND REC<1>,REC<8>,STK.OH
                IF TYPE = 'ONHAND.PER' THEN
                   *** convert the UOM qty.
                   MATREAD PRD FROM PRDFILE,PN ELSE MAT PRD = ''
                   MATREAD PLNE FROM PLNEFILE,PRD(9) ELSE MAT PLNE = ''
                   DFLT.PER.GET 'I',PER,ALPHA
                   IF PRD(15) # '' THEN
                      UMTBL = PRD(15)
                   END ELSE
                      UMTBL = PLNE(3)
                   END
                   IQ.TO.ALPHA UMTBL,PRD(7),ALPHA,STK.OH,,,,,ALPHA
                   STK.OH  = TRIM(ALPHA)
                END
             END ELSE
                STK.OH = 0
             END
             VAL<1,LDN> = STK.OH
          CASE TYPE = 'PN.STK.FLAG'         ;* stock flag
             *** for stock branch only
             STK.BR = LED(2)<1,GEN,2>
             STK.FLAG = ''
             IF NUM(PN) THEN
                GET.PRD.BR.VAL STK.BR,PN,12,STK.FLAG
                IF STK.FLAG ='1' THEN STK.FLAG ='Y' ELSE
                   IF STK.FLAG='0' THEN STK.FLAG='N' ELSE STK.FLAG='-'
                END
             END
             VAL<1,LDN> = STK.FLAG
          CASE TYPE = 'PN.BUY.ID'          ;* buyer's ID
             *** for stock branch only
             STK.BR = LED(2)<1,GEN,2>
             BUY.ID = ''
             IF NUM(PN) THEN
                READV BLINE FROM PRDFILE,PN,12 THEN
                   BUYLINE.BR.GET.VAL STK.BR,BLINE,17,BUY.ID
                END
             END
             VAL<1,LDN> = BUY.ID
          CASE TYPE[1,4] = 'ONPO'
             IF NUM(PN) THEN
                *** for stock branch only
                STK.BR  = LED(2)<1,GEN,2>
                IF TYPE = 'ONPO.DT' THEN            ;* ONPO
                   *** for TYPE = 'ONPO.DT'
                   ONPO.DT = 99999
                END ELSE
                   *** for TYPE = 'ONPO' or 'ONPO.PER'
                   MATREAD PRD FROM PRDFILE,PN ELSE MAT PRD = ''
                   MATREAD PLNE FROM PLNEFILE,PRD(9) ELSE MAT PLNE = ''
                   ONPO    = 0
                END
                PRDD.BR.GET STK.BR,PN
                TRS     = PRDD.BR(2)
                TRN     = DCOUNT(TRS,VM)
                FOR TRX=1 TO TRN
                   IF FIELD(TRS<1,TRX>,'~',3)[1,1]='P' THEN
                      IF TYPE = 'ONPO.DT' THEN
                         *** get the receiving date
                         PO.DT = FIELD(TRS<1,TRX>,'~',2)
                         *** set ONPO.DT to the latest date
                         IF ONPO.DT > PO.DT THEN ONPO.DT = PO.DT
                      END ELSE
                         *** get the QTY
                         ONPO += PRDD.BR(3)<1,TRX>
                      END
                   END
                NEXT TRX
                IF TYPE = 'ONPO.DT' THEN
                   IF ONPO.DT = 99999 THEN ONPO.DT = ''
                   VAL<1,LDN> = ONPO.DT
                END ELSE
                   IF TYPE = 'ONPO.PER' THEN
                      *** convert the UOM qty.
                      DFLT.PER.GET 'P',PER,ALPHA
                      IF PRD(15) # '' THEN
                         UMTBL = PRD(15)
                      END ELSE
                         UMTBL = PLNE(3)
                      END
                      IQ.TO.ALPHA UMTBL,PRD(7),ALPHA,ONPO,,,,,ALPHA
                      ONPO = TRIM(ALPHA)
                   END
                   VAL<1,LDN> = ONPO
                END
             END ELSE
                VAL<1,LDN> = ''
             END
          CASE TYPE[1,7] = 'ON.XFER'            ;* on transter
             *** for stock branch only
             STK.BR = LED(2)<1,GEN,2>
             ONPO = 0
             IF NUM(PN) THEN
                INV.GET.TOTALS PN,STK.BR,STK.OH,TAG.OH,STK.CMTD,TAG.CMTD,STK.PO,TAG.PO,STK.XFER,TAG.XFER,OTHER,ON.BID,STK.INPR,TAG.INPR
                ONPO += STK.XFER
             END
             IF TYPE = 'ON.XFER.PER' THEN
                *** convert the UOM qty.
                MATREAD PRD FROM PRDFILE,PN ELSE MAT PRD = ''
                MATREAD PLNE FROM PLNEFILE,PRD(9) ELSE MAT PLNE = ''
                DFLT.PER.GET 'T',PER,ALPHA
                IF PRD(15) # '' THEN
                   UMTBL = PRD(15)
                END ELSE
                   UMTBL = PLNE(3)
                END
                IQ.TO.ALPHA UMTBL,PRD(7),ALPHA,ONPO,,,,,ALPHA
                ONPO = TRIM(ALPHA)
             END
             VAL<1,LDN> = ONPO
          END CASE

          NEXT LDN

          IF TYPE = 'TAGDT' THEN
             TAG.CT  = DCOUNT(VAL,VM)
             FOR TAG.ID = 1 TO TAG.CT
                TAG = VAL<1,TAG.ID>
                READV SHIP.DT FROM LEDFILE,TAG,9 ELSE SHIP.DT=''
                SHIP.DT = SHIP.DT<1,1>
                VAL<1,TAG.ID> = SHIP.DT
             NEXT TAG.ID
          END

          RETURN
*-------------------------------------------------------------------------*
